אנחנו מתחילים לעבוד על מערכת לרעיון מגניב שחשבנו עליו. עם הזמן והזמן אנחנו מפתחים ומפתחים אותה ובסוף מסתבר שאנחנו יוצרים מחלקה חדשה אבל השם הזה כבר קיים. אם נסתכל על מערכות כמו CodeIgniter, ZF1 או אפילו Yii - הם פתרו את הבעיה הזאת בנתינת prefix כמו Zend_, CI_, או במקרה האחר פשוט C,זה הסתיים בכך שיש מחלקות עם שמות מטורפים כמו "Zend_Application_Bootstrap_Bootstrap" ואף יותר גדולים. בואו נכיר את namespae
אחד הדברים החשובים שהרבה מתכנתים חיכו שהגיע עם הרליס של 5.3 הוא ניימספייס, שעליו נדבר היום במאמר.
מה זה namespace בכלל?
עם הזמן כשאר אנחנו מפתחים מערכת, לבד או בחברה קטנה, המערכת כל הזמן גדלה, אנחנו לוקחים מדי פעם
מחלקות צד שלישי בשביל פעולה מסוימת ואז אנחנו מבינים שיש לנו לפעמים קונפליקט עם הפונקציות או המחלקות - אותו שם בקבצים שונים. עד 5.3, רוב המערכות והפריימוורקים היו עושים prefix למחלקות בסגנון של Zend_Application_Bootstrap_Bootstrap שאומר לנו שבתוך תיקיית זנד, יש תיקיית אפליקשן, בתוכה בוסטראפ ושם נמצאת המחלקה שלנו. זה גרם שהיה מחלקות עם שמות ענקיים, ובכללי הדרך היתה די "מלוכלכת" (messy) ולא נעימה לעין. לכאן נכנס namespace - הוא מגדיר לנו קונטיינר אבסטרקטי שמאפשר לנו לכתוב קוד שמתייחס ספציפית לניימספייס הזה. כלומר, נקח לצורך הדוגמא שיש לנו מחלקת אימייל בתוך תיקיית application ואותה שם של מחלקה בתיקיית core. שתי המחלקות מכילות קוד שונה אך אותו שם, ואנחנו נרצה לטעון את שתי המחלקות בקובץ אחר במערכת, ופשוט נעשה $coreEmail = new \Core\Email; ו - $appEmail = new \Application\Email;, ובכך לצורך הדוגמא נמנענו מקונפליקט מיותר.
הסינטקס
הסינטקס של ניימספייס בPHP מתבטא בשתי צורות, אופציה ראשונה זה לרשום בשורה אחת ואופציה שניה להכניס את כל הקוד של הניימספייס שלנו לתוך סוגריים מסולסלות:
<?php
namespace Application\Database;
// some code
// OR
namespace Application\Database {
// code
}
namespace Application\Database;
// some code
// OR
namespace Application\Database {
// code
}
וככה יצרנו את הקונטיינר הראשון שלנו.
השם של הניימספייס אמור להכיל את הנתיב המלא לקובץ. כלומר, אם יש לנו קובץ בשם Blog.php שנמצא בתוך תיקיית controllers שנמצא בתוך תיקיית application, אז השם של הניימספייס שלנו יהיה: namespace Application\Controllers\Blog.
הסטנדרט psr-0 של קבוצת פיג מסביר לנו מה השם הראוי לניימספייס.
הזיהוי של הניימספייס שאנחנו מתייחסים אליו מחולק לשלוש קבוצות:
1. Fully qualified name
Fully qualified name מתייחס לנתיב המלא למיקום של הניימספייס שאנחנו מתכוונים אליו במערכת קבצים.
כלומר, אם אנחנו נשתמש בניימספייס \Foo\Bar\MyClass הוא יחפש את המחלקה MyClass בתוך הניימספייס Foo\Bar.
2. Qualified name
Qualified name מתייחס לנתיב שנמצא בניימספייס שאנחנו משתמשים בו כרגע. כלומר, אם אנחנו כרגע נמצאים בניימספייס בשם \Foo\Bar ואנחנו מנסים לגשת לLibs\Someclass הוא יחפש את המחלקה בנתיב \Foo\Bar\Libs\Someclass. שימו לב, שאם הינו שמים \ לפני Libs, הוא היה לא מתייחס לזה כחלק מ\Foo\Bar והיה הולך ישירות ל\Libs\Someclass.
3. Unqualified name
Unqualified name מתייחס כמובן לנתיב הנוכחי שאנחנו עובדים בו. אם ניצור אינטנט חדש של מחלקה, או נשתמש בפונקציה מסוימת תחת הניימספייס \Foo\Bar הוא יחפש אותם באותו ניימספייס.
למי שאיבד אותי, הינה קוד קטן שימחיש את הקטגוריות:
<?php
namespace Foo;
class Someclass {}
function Somefunction() {}
// Fully qualified name
$myMailClass = new \Libs\AwesomeMail\Mailer;
\Core\Functions\addViewToDb();
// Qualified name
$otherClass = new Bar\Baz; // Will reffer this as Foo\Bar\Baz
Bar\awesomeFunction(); // The same ^
// Unqualified name
$lastClass = new Someclass; // Reffers to the current namespace class
Somefunction();
namespace Foo;
class Someclass {}
function Somefunction() {}
// Fully qualified name
$myMailClass = new \Libs\AwesomeMail\Mailer;
\Core\Functions\addViewToDb();
// Qualified name
$otherClass = new Bar\Baz; // Will reffer this as Foo\Bar\Baz
Bar\awesomeFunction(); // The same ^
// Unqualified name
$lastClass = new Someclass; // Reffers to the current namespace class
Somefunction();
עכשיו, כשאנחנו נרצה ליצור אינסנטס חדש של מחלקה מובנת בPHP, ניצטרך לגשת אלייה עם סלאש אחורי בהתחלה:
<?php
namespace Framework\Database;
class Database {
public function __construct($dsn, $user = "", $pass = "", $drivers = array()) {
$pdo = new \PDO($dsn, $user, $pass, $drivers);
}
}
namespace Framework\Database;
class Database {
public function __construct($dsn, $user = "", $pass = "", $drivers = array()) {
$pdo = new \PDO($dsn, $user, $pass, $drivers);
}
}
אומנם זה לא תקף לפונקציות המובנות:
<?php
namespace Libs\Functions\FileManager;
function file_get_contents($filename) {
return true;
}
$filename = "fakefile.jaja";
var_dump(file_get_contents($filename)); // bool(true)
var_dump(\file_get_contents($filename)); // bool(false) and probably an E_WARNING
var_dump(strlen($filename)); // int(13), as we didn't overried the function so it looks up to the built-in functions
namespace Libs\Functions\FileManager;
function file_get_contents($filename) {
return true;
}
$filename = "fakefile.jaja";
var_dump(file_get_contents($filename)); // bool(true)
var_dump(\file_get_contents($filename)); // bool(false) and probably an E_WARNING
var_dump(strlen($filename)); // int(13), as we didn't overried the function so it looks up to the built-in functions
use
כשאנחנו רוצים להשתמש בכמה ניימספייסים ארוכים בקובץ אצלינו במערכת, רוב הסיכויים שיהיה מבאס לכתוב את כל הנתיב (Fully qualified name), לשם כך יש לנו את המילה השמורה: use.
כאשר אנחנו משתמשים בה בקוד, אנחנו מציינים את הנתיב של הניימספייס/ים שלנו, ובכך אנחנו מאפשרים לעצמנו שימוש עם Qualified name או Unqualified name במקום לרשום את כל הנתיב.
לדוגמא:
<?php
use \Foo\Bar\Baz\Gaz\Shmaz;
use \AwesomeFramework\Libs\UnveryNeedenStuff\FacebookAPI;
Shmaz\ShmazIT("yes!"); // Reffers to \Foo\Bar\Baz\Gaz\Shmaz
new FacebookAPI("mySecretKey"); // Reffers to \AwesomeFramework\Libs\UnveryNeedenStuff\FacebookAPI
new \FacebookAPI("otherClass"); // Does not affected by \AwesomeFramework\Libs\UnveryNeedenStuff\FacebookAPI
use \Foo\Bar\Baz\Gaz\Shmaz;
use \AwesomeFramework\Libs\UnveryNeedenStuff\FacebookAPI;
Shmaz\ShmazIT("yes!"); // Reffers to \Foo\Bar\Baz\Gaz\Shmaz
new FacebookAPI("mySecretKey"); // Reffers to \AwesomeFramework\Libs\UnveryNeedenStuff\FacebookAPI
new \FacebookAPI("otherClass"); // Does not affected by \AwesomeFramework\Libs\UnveryNeedenStuff\FacebookAPI
ואפילו הוסיפו לנו את המילה as שמאפשרת לתת alias לניימספייסים:
<?php
use \Foo\Bar\Baz\Gaz\Shmaz as ShmazFunctions;
use \AwesomeFramework\Libs\UnveryNeedenStuff\FacebookAPI as FB;
ShmazFunctions\ShmazIT("yes!");
new FB\FacebookAPI("mySecretKey");
use \Foo\Bar\Baz\Gaz\Shmaz as ShmazFunctions;
use \AwesomeFramework\Libs\UnveryNeedenStuff\FacebookAPI as FB;
ShmazFunctions\ShmazIT("yes!");
new FB\FacebookAPI("mySecretKey");
לסיכום
ניימספייס הוא תכונה חזקה שמאפשרת לנו לפתח מערכות ואת הארכיאקטורה שלהם בצורה יותר חכמה ונקייה.
השימוש פשוט, התוצאות טובות.
אפשר לקרוא עוד על ניימספייס בphp.net :)
תגובות לכתבה:
תודה רבה על המדריך ... חידשת לי :)
אחלה מדריך. תודה. :-)
אולי כדאי להוסיף קישור למאמר על PSR-0 באתר... http://phpguide.co.il/psr0.htm
מדריך נחמד , למרות שכבר יש כזה בעברית.
בקיצור מיותר.
תצטרף קישור. יהיה שני מדריכים.
אם אתה חושב שזה מיותר, אתה מוזמן לכתוב בעצמך מאמר לאתר על נושא שלא כתבו עליו עדיין =)
יש לי אתר של מדריכים:
http://lior-portal.co.il
אתה יכול להיכנס להתעדכן במדריכים על התכנות (לא רק PHP)
המאמר נמצא כאן:
http://www.internet-israel.com/internet/פיתוח-אינטרנט/בניית-אתרי-אינטרנט-למפתחים/php-5-3-namespacing/
אחלה אתר מדריכים ותודה על הקישור למדריך של רן. לדעתי מיכאל פשוט פירט את הנושא עוד יותר
בתקווה שזה יגרום לך ולמתכנתים אחרים להתחיל להשתבש בזה ואולי אפילו לכתוב את המדריך השלישי :)
תודה רבה , אשמח אם תיצור איתי קשר באימייל\סקייפ\FXP (יהומלך).
אם אתה חושב שזה חיוני אני באמת יפרסם על זה מדריך , אני מחפש דברים מעניינים לפרסם עליהם.